home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 101-125 / scopedisk110 / lzcomp / lzhuf.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  14KB  |  631 lines

  1. /*
  2. LZHUF.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
  3. All rights reserved. Permission granted for non-commercial use.
  4. */
  5. /*
  6. -- Kenji
  7. -- 
  8. Kenji Rikitake: rikitake@wadalab.t.u-tokyo.junet +81 3 812 2111 ext 7411
  9. Kenji%dctwcs.das.net@(Sun.COM|uunet.uu.net) +81 3 351 5977
  10. Michihiro Matsumoto Office / MDI: +81 3 823 7943
  11. */
  12. /**************************************************************
  13.     lzhuf.c
  14.     written by Haruyasu Yoshizaki 11/20/1988
  15.     some minor changes 4/6/1989
  16.     comments translated by Haruhiko Okumura 4/7/1989
  17. **************************************************************/
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22.  
  23. FILE  *infile, *outfile;
  24. unsigned long int  textsize = 0, codesize = 0, printcount = 0;
  25.  
  26. char wterr[] = "Can't write.";
  27.  
  28. void Error(char *message)
  29. {
  30.     printf("\n%s\n", message);
  31.     exit(EXIT_FAILURE);
  32. }
  33.  
  34. /********** LZSS compression **********/
  35.  
  36. #define N        4096    /* buffer size */
  37. #define F        60    /* lookahead buffer size */
  38. #define THRESHOLD    2
  39. #define NIL        N    /* leaf of tree */
  40.  
  41. unsigned char
  42.         text_buf[N + F - 1];
  43. int        match_position, match_length,
  44.         lson[N + 1], rson[N + 257], dad[N + 1];
  45.  
  46. void InitTree(void)  /* initialize trees */
  47. {
  48.     int  i;
  49.  
  50.     for (i = N + 1; i <= N + 256; i++)
  51.         rson[i] = NIL;            /* root */
  52.     for (i = 0; i < N; i++)
  53.         dad[i] = NIL;            /* node */
  54. }
  55.  
  56. void InsertNode(int r)  /* insert to tree */
  57. {
  58.     int  i, p, cmp;
  59.     unsigned char  *key;
  60.     unsigned c;
  61.  
  62.     cmp = 1;
  63.     key = &text_buf[r];
  64.     p = N + 1 + key[0];
  65.     rson[r] = lson[r] = NIL;
  66.     match_length = 0;
  67.     for ( ; ; ) {
  68.         if (cmp >= 0) {
  69.             if (rson[p] != NIL)
  70.                 p = rson[p];
  71.             else {
  72.                 rson[p] = r;
  73.                 dad[r] = p;
  74.                 return;
  75.             }
  76.         } else {
  77.             if (lson[p] != NIL)
  78.                 p = lson[p];
  79.             else {
  80.                 lson[p] = r;
  81.                 dad[r] = p;
  82.                 return;
  83.             }
  84.         }
  85.         for (i = 1; i < F; i++)
  86.             if ((cmp = key[i] - text_buf[p + i]) != 0)
  87.                 break;
  88.         if (i > THRESHOLD) {
  89.             if (i > match_length) {
  90.                 match_position = ((r - p) & (N - 1)) - 1;
  91.                 if ((match_length = i) >= F)
  92.                     break;
  93.             }
  94.             if (i == match_length) {
  95.                 if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
  96.                     match_position = c;
  97.                 }
  98.             }
  99.         }
  100.     }
  101.     dad[r] = dad[p];
  102.     lson[r] = lson[p];
  103.     rson[r] = rson[p];
  104.     dad[lson[p]] = r;
  105.     dad[rson[p]] = r;
  106.     if (rson[dad[p]] == p)
  107.         rson[dad[p]] = r;
  108.     else
  109.         lson[dad[p]] = r;
  110.     dad[p] = NIL;  /* remove p */
  111. }
  112.  
  113. void DeleteNode(int p)  /* remove from tree */
  114. {
  115.     int  q;
  116.  
  117.     if (dad[p] == NIL)
  118.         return;            /* not registered */
  119.     if (rson[p] == NIL)
  120.         q = lson[p];
  121.     else
  122.     if (lson[p] == NIL)
  123.         q = rson[p];
  124.     else {
  125.         q = lson[p];
  126.         if (rson[q] != NIL) {
  127.             do {
  128.                 q = rson[q];
  129.             } while (rson[q] != NIL);
  130.             rson[dad[q]] = lson[q];
  131.             dad[lson[q]] = dad[q];
  132.             lson[q] = lson[p];
  133.             dad[lson[p]] = q;
  134.         }
  135.         rson[q] = rson[p];
  136.         dad[rson[p]] = q;
  137.     }
  138.     dad[q] = dad[p];
  139.     if (rson[dad[p]] == p)
  140.         rson[dad[p]] = q;
  141.     else
  142.         lson[dad[p]] = q;
  143.     dad[p] = NIL;
  144. }
  145.  
  146. /* Huffman coding */
  147.  
  148. #define N_CHAR      (256 - THRESHOLD + F)
  149.                 /* kinds of characters (character code = 0..N_CHAR-1) */
  150. #define T         (N_CHAR * 2 - 1)    /* size of table */
  151. #define R         (T - 1)            /* position of root */
  152. #define MAX_FREQ    0x8000        /* updates tree when the */
  153.                     /* root frequency comes to this value. */
  154. typedef unsigned char uchar;
  155.  
  156.  
  157. /* table for encoding and decoding the upper 6 bits of position */
  158.  
  159. /* for encoding */
  160. uchar p_len[64] = {
  161.     0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
  162.     0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
  163.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  164.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  165.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  166.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  167.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  168.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
  169. };
  170.  
  171. uchar p_code[64] = {
  172.     0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
  173.     0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
  174.     0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
  175.     0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
  176.     0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
  177.     0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
  178.     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  179.     0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
  180. };
  181.  
  182. /* for decoding */
  183. uchar d_code[256] = {
  184.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  185.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  186.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  187.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  188.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  189.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  190.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  191.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  192.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  193.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  194.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  195.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  196.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  197.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  198.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  199.     0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
  200.     0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
  201.     0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
  202.     0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
  203.     0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
  204.     0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
  205.     0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
  206.     0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
  207.     0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
  208.     0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
  209.     0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
  210.     0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
  211.     0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
  212.     0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
  213.     0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
  214.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  215.     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  216. };
  217.  
  218. uchar d_len[256] = {
  219.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  220.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  221.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  222.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  223.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  224.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  225.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  226.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  227.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  228.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  229.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  230.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  231.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  232.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  233.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  234.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  235.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  236.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  237.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  238.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  239.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  240.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  241.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  242.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  243.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  244.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  245.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  246.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  247.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  248.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  249.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  250.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  251. };
  252.  
  253. unsigned freq[T + 1];    /* frequency table */
  254.  
  255. int prnt[T + N_CHAR];    /* pointers to parent nodes, except for the */
  256.             /* elements [T..T + N_CHAR - 1] which are used to get */
  257.             /* the positions of leaves corresponding to the codes. */
  258.  
  259. int son[T];        /* pointers to child nodes (son[], son[] + 1) */
  260.  
  261. unsigned getbuf = 0;
  262. uchar getlen = 0;
  263.  
  264. int GetBit(void)    /* get one bit */
  265. {
  266.     int i;
  267.  
  268.     while (getlen <= 8) {
  269.         if ((i = getc(infile)) < 0) i = 0;
  270.         getbuf |= i << (8 - getlen);
  271.         getlen += 8;
  272.     }
  273.     i = getbuf;
  274.     getbuf <<= 1;
  275.     getlen--;
  276.     return (i < 0);
  277. }
  278.  
  279. int GetByte(void)    /* get one byte */
  280. {
  281.     unsigned i;
  282.  
  283.     while (getlen <= 8) {
  284.         if ((i = getc(infile)) < 0) i = 0;
  285.         getbuf |= i << (8 - getlen);
  286.         getlen += 8;
  287.     }
  288.     i = getbuf;
  289.     getbuf <<= 8;
  290.     getlen -= 8;
  291.     return i >> 8;
  292. }
  293.  
  294. unsigned putbuf = 0;
  295. uchar putlen = 0;
  296.  
  297. void Putcode(int l, unsigned c)        /* output c bits of code */
  298. {
  299.     putbuf |= c >> putlen;
  300.     if ((putlen += l) >= 8) {
  301.         if (putc(putbuf >> 8, outfile) == EOF) {
  302.             Error(wterr);
  303.         }
  304.         if ((putlen -= 8) >= 8) {
  305.             if (putc(putbuf, outfile) == EOF) {
  306.                 Error(wterr);
  307.             }
  308.             codesize += 2;
  309.             putlen -= 8;
  310.             putbuf = c << (l - putlen);
  311.         } else {
  312.             putbuf <<= 8;
  313.             codesize++;
  314.         }
  315.     }
  316. }
  317.  
  318.  
  319. /* initialization of tree */
  320.  
  321. void StartHuff(void)
  322. {
  323.     int i, j;
  324.  
  325.     for (i = 0; i < N_CHAR; i++) {
  326.         freq[i] = 1;
  327.         son[i] = i + T;
  328.         prnt[i + T] = i;
  329.     }
  330.     i = 0; j = N_CHAR;
  331.     while (j <= R) {
  332.         freq[j] = freq[i] + freq[i + 1];
  333.         son[j] = i;
  334.         prnt[i] = prnt[i + 1] = j;
  335.         i += 2; j++;
  336.     }
  337.     freq[T] = 0xffff;
  338.     prnt[R] = 0;
  339. }
  340.  
  341.  
  342. /* reconstruction of tree */
  343.  
  344. void reconst(void)
  345. {
  346.     int i, j, k;
  347.     unsigned f, l;
  348.  
  349.     /* collect leaf nodes in the first half of the table */
  350.     /* and replace the freq by (freq + 1) / 2. */
  351.     j = 0;
  352.     for (i = 0; i < T; i++) {
  353.         if (son[i] >= T) {
  354.             freq[j] = (freq[i] + 1) / 2;
  355.             son[j] = son[i];
  356.             j++;
  357.         }
  358.     }
  359.     /* begin constructing tree by connecting sons */
  360.     for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  361.         k = i + 1;
  362.         f = freq[j] = freq[i] + freq[k];
  363.         for (k = j - 1; f < freq[k]; k--);
  364.         k++;
  365.         l = (j - k) * 2;
  366.         memmove(&freq[k + 1], &freq[k], l);
  367.         freq[k] = f;
  368.         memmove(&son[k + 1], &son[k], l);
  369.         son[k] = i;
  370.     }
  371.     /* connect prnt */
  372.     for (i = 0; i < T; i++) {
  373.         if ((k = son[i]) >= T) {
  374.             prnt[k] = i;
  375.         } else {
  376.             prnt[k] = prnt[k + 1] = i;
  377.         }
  378.     }
  379. }
  380.  
  381.  
  382. /* increment frequency of given code by one, and update tree */
  383.  
  384. void update(int c)
  385. {
  386.     int i, j, k, l;
  387.  
  388.     if (freq[R] == MAX_FREQ) {
  389.         reconst();
  390.     }
  391.     c = prnt[c + T];
  392.     do {
  393.         k = ++freq[c];
  394.  
  395.         /* if the order is disturbed, exchange nodes */
  396.         if (k > freq[l = c + 1]) {
  397.             while (k > freq[++l]);
  398.             l--;
  399.             freq[c] = freq[l];
  400.             freq[l] = k;
  401.  
  402.             i = son[c];
  403.             prnt[i] = l;
  404.             if (i < T) prnt[i + 1] = l;
  405.  
  406.             j = son[l];
  407.             son[l] = i;
  408.  
  409.             prnt[j] = c;
  410.             if (j < T) prnt[j + 1] = c;
  411.             son[c] = j;
  412.  
  413.             c = l;
  414.         }
  415.     } while ((c = prnt[c]) != 0);    /* repeat up to root */
  416. }
  417.  
  418. unsigned code, len;
  419.  
  420. void EncodeChar(unsigned c)
  421. {
  422.     unsigned i;
  423.     int j, k;
  424.  
  425.     i = 0;
  426.     j = 0;
  427.     k = prnt[c + T];
  428.  
  429.     /* travel from leaf to root */
  430.     do {
  431.         i >>= 1;
  432.  
  433.         /* if node's address is odd-numbered, choose bigger brother node */
  434.         if (k & 1) i += 0x8000;
  435.  
  436.         j++;
  437.     } while ((k = prnt[k]) != R);
  438.     Putcode(j, i);
  439.     code = i;
  440.     len = j;
  441.     update(c);
  442. }
  443.  
  444. void EncodePosition(unsigned c)
  445. {
  446.     unsigned i;
  447.  
  448.     /* output upper 6 bits by table lookup */
  449.     i = c >> 6;
  450.     Putcode(p_len[i], (unsigned)p_code[i] << 8);
  451.  
  452.     /* output lower 6 bits verbatim */
  453.     Putcode(6, (c & 0x3f) << 10);
  454. }
  455.  
  456. void EncodeEnd(void)
  457. {
  458.     if (putlen) {
  459.         if (putc(putbuf >> 8, outfile) == EOF) {
  460.             Error(wterr);
  461.         }
  462.         codesize++;
  463.     }
  464. }
  465.  
  466. int DecodeChar(void)
  467. {
  468.     unsigned c;
  469.  
  470.     c = son[R];
  471.  
  472.     /* travel from root to leaf, */
  473.     /* choosing the smaller child node (son[]) if the read bit is 0, */
  474.     /* the bigger (son[]+1} if 1 */
  475.     while (c < T) {
  476.         c += GetBit();
  477.         c = son[c];
  478.     }
  479.     c -= T;
  480.     update(c);
  481.     return c;
  482. }
  483.  
  484. int DecodePosition(void)
  485. {
  486.     unsigned i, j, c;
  487.  
  488.     /* recover upper 6 bits from table */
  489.     i = GetByte();
  490.     c = (unsigned)d_code[i] << 6;
  491.     j = d_len[i];
  492.  
  493.     /* read lower 6 bits verbatim */
  494.     j -= 2;
  495.     while (j--) {
  496.         i = (i << 1) + GetBit();
  497.     }
  498.     return c | (i & 0x3f);
  499. }
  500.  
  501. /* compression */
  502.  
  503. void Encode(void)  /* compression */
  504. {
  505.     int  i, c, len, r, s, last_match_length;
  506.  
  507.     fseek(infile, 0L, 2);
  508.     textsize = ftell(infile);
  509.     if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1)
  510.         Error(wterr);    /* output size of text */
  511.     if (textsize == 0)
  512.         return;
  513.     rewind(infile);
  514.     textsize = 0;            /* rewind and re-read */
  515.     StartHuff();
  516.     InitTree();
  517.     s = 0;
  518.     r = N - F;
  519.     for (i = s; i < r; i++)
  520.         text_buf[i] = ' ';
  521.     for (len = 0; len < F && (c = getc(infile)) != EOF; len++)
  522.         text_buf[r + len] = c;
  523.     textsize = len;
  524.     for (i = 1; i <= F; i++)
  525.         InsertNode(r - i);
  526.     InsertNode(r);
  527.     do {
  528.         if (match_length > len)
  529.             match_length = len;
  530.         if (match_length <= THRESHOLD) {
  531.             match_length = 1;
  532.             EncodeChar(text_buf[r]);
  533.         } else {
  534.             EncodeChar(255 - THRESHOLD + match_length);
  535.             EncodePosition(match_position);
  536.         }
  537.         last_match_length = match_length;
  538.         for (i = 0; i < last_match_length &&
  539.                 (c = getc(infile)) != EOF; i++) {
  540.             DeleteNode(s);
  541.             text_buf[s] = c;
  542.             if (s < F - 1)
  543.                 text_buf[s + N] = c;
  544.             s = (s + 1) & (N - 1);
  545.             r = (r + 1) & (N - 1);
  546.             InsertNode(r);
  547.         }
  548.         if ((textsize += i) > printcount) {
  549.             printf("%12ld\r", textsize);
  550.             printcount += 1024;
  551.         }
  552.         while (i++ < last_match_length) {
  553.             DeleteNode(s);
  554.             s = (s + 1) & (N - 1);
  555.             r = (r + 1) & (N - 1);
  556.             if (--len) InsertNode(r);
  557.         }
  558.     } while (len > 0);
  559.     EncodeEnd();
  560.     printf("In : %ld bytes\n", textsize);
  561.     printf("Out: %ld bytes\n", codesize);
  562.     printf("Out/In: %.3f\n", (double)codesize / textsize);
  563. }
  564.  
  565. void Decode(void)  /* recover */
  566. {
  567.     int  i, j, k, r, c;
  568.     unsigned long int  count;
  569.  
  570.     if (fread(&textsize, sizeof textsize, 1, infile) < 1)
  571.         Error("Can't read");  /* read size of text */
  572.     if (textsize == 0)
  573.         return;
  574.     StartHuff();
  575.     for (i = 0; i < N - F; i++)
  576.         text_buf[i] = ' ';
  577.     r = N - F;
  578.     for (count = 0; count < textsize; ) {
  579.         c = DecodeChar();
  580.         if (c < 256) {
  581.             if (putc(c, outfile) == EOF) {
  582.                 Error(wterr);
  583.             }
  584.             text_buf[r++] = c;
  585.             r &= (N - 1);
  586.             count++;
  587.         } else {
  588.             i = (r - DecodePosition() - 1) & (N - 1);
  589.             j = c - 255 + THRESHOLD;
  590.             for (k = 0; k < j; k++) {
  591.                 c = text_buf[(i + k) & (N - 1)];
  592.                 if (putc(c, outfile) == EOF) {
  593.                     Error(wterr);
  594.                 }
  595.                 text_buf[r++] = c;
  596.                 r &= (N - 1);
  597.                 count++;
  598.             }
  599.         }
  600.         if (count > printcount) {
  601.             printf("%12ld\r", count);
  602.             printcount += 1024;
  603.         }
  604.     }
  605.     printf("%12ld\n", count);
  606. }
  607.  
  608. int main(int argc, char *argv[])
  609. {
  610.     char  *s;
  611.  
  612.     if (argc != 4) {
  613.         printf("'lzhuf e file1 file2' encodes file1 into file2.\n"
  614.                "'lzhuf d file2 file1' decodes file2 into file1.\n");
  615.         return EXIT_FAILURE;
  616.     }
  617.     if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
  618.      || (s = argv[2], (infile  = fopen(s, "rb")) == NULL)
  619.      || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
  620.         printf("??? %s\n", s);
  621.         return EXIT_FAILURE;
  622.     }
  623.     if (toupper(*argv[1]) == 'E')
  624.         Encode();
  625.     else
  626.         Decode();
  627.     fclose(infile);
  628.     fclose(outfile);
  629.     return EXIT_SUCCESS;
  630. }
  631.